import os


from langchain_milvus import Milvus, BM25BuiltInFunction
from langchain_milvus.utils.sparse import BM25SparseEmbedding
from langchain_ollama import ChatOllama, OllamaEmbeddings

from typing import List
from langchain_core.embeddings import Embeddings
from langchain_openai import ChatOpenAI

from config.DBConfig import DOC_COLLECTION_NAME, MILVUS_RUL
from config.LLMConfig import TONGYI_API_KEY, OLLAMA_EMBEDDING_MODEL, OLLAMA_EMBEDDING_URL


def chat_llm(param: dict = None):
    """
    LLM 聊天模型，用于调用指定模型进行对话生成

    参数:
        param (dict): 包含模型配置的字典，必须包含以下字段：
            - model (str): 使用的模型名称，默认为 "qwen-plus"
            - base_url (str): 模型服务的基础 URL，默认为阿里云 DashScope 兼容模式地址
            - temperature (float): 生成文本的温度值，默认为 0.3

    返回:
        无（当前仅为接口定义，具体实现待补充）

    异常:
        ValueError: 如果 param 缺少必要字段，则抛出异常
    """
    if param is None:
        param = {
            "model": "qwen-plus",
            "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
            "temperature": 0.3,
            "api_key": TONGYI_API_KEY
        }

    required_keys = ["model", "base_url", "temperature"]
    for key in required_keys:
        if key not in param:
            raise ValueError(f"Missing required parameter: {key}")
    """LLM 聊天模型"""

    # 初始化模型
    llm = ChatOpenAI(**param)

    # 方式一：调用本地模型，调用 langchain_ollama 库下的 ChatOllama
    # 导入包：from langchain_ollama import ChatOllama
    # llm = ChatOllama(
    #     model=MODEL_NAME,
    #     temperature=0.1,
    #     streaming=True,
    #     callbacks=[StreamingStdOutCallbackHandler()],
    # )

    # 方式二：调用 langchain_deepseek 库下的 ChatDeepSeek 工具类
    # 导入包：from langchain_deepseek import ChatDeepSeek
    # llm = ChatDeepSeek(
    #     model="deepseek-reasoner",
    #     api_key=API_KEY,
    #     base_url="https://api.deepseek.com/v1",
    # )

    # 方式三：调用 langchain_openai 库下的 ChatOpenAI 工具类
    # 导入包：from langchain_openai import ChatOpenAI
    # llm = ChatOpenAI(
    #     model="deepseek-reasoner",
    #     api_key=API_KEY,
    #     base_url="https://api.deepseek.com/v1",
    #     callbacks=[StreamingStdOutCallbackHandler()],
    # )

    return llm




def milvus_vector_store(drop_old:  bool = False):
    """Chroma 向量数据库"""

    return Milvus(
        builtin_function=BM25BuiltInFunction(output_field_names="sparse"),  # output_field_names="sparse"),
        embedding_function=[dense_embeddings_model()],
        vector_field=["dense", "sparse"],
        metadata_field="metadata",
        text_field="text",
        connection_args={"uri": MILVUS_RUL},
        consistency_level="Bounded",  # Supported values are (`"Strong"`, `"Session"`, `"Bounded"`, `"Eventually"`). See https://milvus.io/docs/consistency.md#Consistency-Level for more details.
        collection_name=DOC_COLLECTION_NAME,
        drop_old=drop_old,  # 如果集合已存在，删除旧集合

        auto_id=True  # 自动生成唯一 ID
    )


def dense_embeddings_model():
    """Embedding 模型"""

    # 方式一：调用 Ollama 服务的 embedding 模型，使用下载量第一的 nomic-embed-text embedding 模型
    # 导入包：from langchain_ollama import OllamaEmbeddings
    # https://ollama.com/library/nomic-embed-text
    embeddings = OllamaEmbeddings(model=OLLAMA_EMBEDDING_MODEL, base_url=OLLAMA_EMBEDDING_URL)

    #embeddings = OllamaEmbeddings(model=OLLAMA_EMBEDDING_NAME)

    # 以下方式使用 bge-base-zh-v1.5 embedding 模型，请前往 HuggingFace 下载：
    # https://huggingface.co/BAAI/bge-base-zh-v1.5

    # 方式二：调用 langchain_community.embeddings 库下的 HuggingFaceBgeEmbeddings
    # 导入包： from langchain_community.embeddings import HuggingFaceBgeEmbeddings
    # embeddings = HuggingFaceBgeEmbeddings(
    #     model_name=EMBEDDING_MODEL_PATH,
    # )

    # 方式三：调用 langchain_huggingface 库下的 HuggingFaceEmbeddings
    # 导入包： from langchain_huggingface import HuggingFaceEmbeddings
    # 适用于支持 HuggingFace Transformers 和 Sentence-Transformers 的 embedding 模型
    # embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL_PATH)

    # 方式四：自定义 Embedding 接口实现
    # embeddings = CustomEmbeddings()

    return embeddings


class CustomEmbeddings(Embeddings):
    """自定义 Embedding 接口实现"""





    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        """Embed search docs."""

        embeddings = [self.model.encode(x) for x in texts]
        return embeddings

    def embed_query(self, text: str) -> List[float]:
        """Embed query text."""
        return self.embed_documents([text])[0]
